use anyhow::{anyhow, Result};
use reqwest::{multipart, Client, Proxy};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tokio::fs;
use url::form_urlencoded;

#[derive(Debug, Deserialize)]
pub struct ReturnInfo {
    pub path: Option<String>,
    #[serde(rename = "isSuccess")]
    pub is_success: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct UploadParam {
    #[serde(rename = "foldername")]
    pub folder_name: String,
    pub ext: String,
}

impl UploadParam {
    pub fn new(folder_name: String, ext: String) -> Self {
        Self { folder_name, ext }
    }
}

pub async fn upload_file(
    host: &str,
    bs: &[u8],
    param: &UploadParam,
    proxy: Option<&str>,
) -> Result<ReturnInfo> {
    // 构建查询参数
    let mut params = HashMap::new();
    params.insert("mod", "uploadfile");
    params.insert("foldername", param.folder_name.as_str());
    params.insert("ext", param.ext.as_str());

    let query_string = form_urlencoded::Serializer::new(String::new())
        .extend_pairs(params.iter())
        .finish();

    let url = format!("{}?{}", host, query_string);

    // 创建客户端
    let mut client_builder = Client::builder();

    if let Some(proxy_url) = proxy {
        client_builder = client_builder.proxy(Proxy::all(proxy_url)?);
    }

    let client = client_builder.build()?;

    // 创建 multipart form
    let part = multipart::Part::bytes(bs.to_vec())
        .file_name("file") // 根据需要设置文件名
        .mime_str("application/octet-stream")?;

    let form = multipart::Form::new().part("file", part);

    // 发送请求
    let response = client.post(&url).multipart(form).send().await?;

    // 处理响应
    if response.status().is_success() {
        let body = response.text().await?;
        let return_info: ReturnInfo = serde_json::from_str(&body)?;
        Ok(return_info)
    } else {
        let error_body = response.text().await?;
        Err(anyhow!("Server error: {}", error_body))
    }
}

pub async fn upload_directory_files(
    video_directory: &str,
    unique_directory: &str,
) -> (bool, String) {
    let result_path: String;
    let has_err: bool;

    match try_upload_directory_files(video_directory, unique_directory).await {
        Ok((err, path)) => {
            has_err = err;
            result_path = path;
        }
        Err(e) => {
            has_err = true;
            result_path = e.to_string();
        }
    }

    (has_err, result_path)
}

async fn try_upload_directory_files(
    video_directory: &str,
    unique_directory: &str,
) -> Result<(bool, String)> {
    let mut result_path = String::new();
    let mut has_err = false;

    // 获取文件夹内的所有文件 - 使用正确的流处理方式
    let mut entries = fs::read_dir(video_directory).await?;

    while let Some(entry) = entries.next_entry().await? {
        let path = entry.path();
        if path.is_file() {
            // 上传到 store
            let file_ext = path
                .extension()
                .and_then(|ext| ext.to_str())
                .unwrap_or("")
                .to_string();

            let param = UploadParam::new(format!("m3u8_videos\\{}", unique_directory), file_ext);

            const HOST: &str = "http://158.255.2.96";
            let file_data = fs::read(&path).await?;
            // 传递 &file_data 而不是 file_data
            match upload_file(HOST, &file_data, &param, None).await {
                Ok(ri) => {
                    if ri.is_success {
                        if let Some(file_path) = path.to_str() {
                            if file_path.ends_with(".m3u8") {
                                if let Some(p) = ri.path {
                                    result_path = p;
                                }
                            }
                        }
                    } else {
                        has_err = true;
                        if let Some(p) = ri.path {
                            result_path = p;
                        }
                    }
                }
                Err(e) => {
                    has_err = true;
                    result_path = e.to_string();
                    break; // 或者继续处理其他文件，根据需求决定
                }
            }
        }
    }

    Ok((has_err, result_path))
}
